const express = require('express');
const fs = require('fs');
const path = require('path');
var router = express.Router();
const crypto = require('crypto');
const app = express();
app.use(express.json());

app.use(express.urlencoded({ extended: true }));

// 检查上传目录是否存在，如果不存在则创建
const uploadDir = path.join(__dirname, 'uploads');// 上传目录
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir);// 创建目录
}

// 文件分片上传接口
router.post('/upload', (req, res) => {
  const fileName = decodeURIComponent(req.headers['file-name']); // 对文件名进行解码
  const filePath = path.join(uploadDir, `${fileName}.${req.headers['file-index']}`);// 获取文件路径

  const writeStream = fs.createWriteStream(filePath);// 创建写入流
  req.pipe(writeStream);// 将请求数据流写入文件

  writeStream.on('finish', () => {
    console.log(`分片 ${req.headers['file-index']} 上传成功，路径: ${filePath}`);
    res.status(200).send('分片上传成功');
  });

  writeStream.on('error', (err) => {
    console.error(`分片 ${req.headers['file-index']} 上传失败:`, err);
    res.status(500).send('分片上传失败');
  });
});

// 查询已上传的分片
router.get('/uploaded-chunks', (req, res) => {
  const fileName = decodeURIComponent(req.query.fileName); // 对文件名进行解码
  //   const filePath = path.join(uploadDir, fileName);// 文件名
  const chunks = [];
  // 遍历文件夹，查找已存在的分片
  // fs.readdir(path.dirname(filePath), (err, files) => {
  fs.readdir(uploadDir, (err, files) => {
    if (err) {
      res.status(500).send('读取文件夹失败');
      return;
    }

    files.forEach(file => {
      if (file.startsWith(`${fileName}.`)) {
        const index = file.split('.').slice(-1)[0];// 获取文件名中的索引部分
        chunks.push(index);// 将索引添加到chunks数组中
      }
    });

    res.status(200).json(chunks);// 返回已上传的分片列表
  });
});



// 合并分片
function mergeChunks(totalChunks, uploadDir, fileName, res) {
  let chunksWritten = 0;
  let hasError = false;
  const writeStream = fs.createWriteStream(path.join(uploadDir, fileName));

  function processChunk(i) {// 合并分片
    if (i >= totalChunks || hasError) {// 如果所有分片都处理完毕或者有错误发生，则停止处理
      return;
    }
    const chunkPath = path.join(uploadDir, `${fileName}.${i}`);// 分片文件路径
    if (!fs.existsSync(chunkPath)) {
      console.error(`分片 ${i} 不存在，路径: ${chunkPath}`);// 如果分片文件不存在，则输出错误信息
      res.status(404).send(`分片 ${i} 不存在`); // 返回错误信息
      hasError = true;
      return;
    }

    const readStream = fs.createReadStream(chunkPath);// 创建分片文件的读取流

    readStream.pipe(writeStream, { end: false });// 将分片文件的内容写入合并文件中

    readStream.on('end', () => {
      fs.unlinkSync(chunkPath);
      console.log(`分片 ${i} 合并完成，路径: ${chunkPath}`);
      chunksWritten++;// 分片处理完成，计数器加1

      if (chunksWritten === totalChunks) {// 如果所有分片都处理完毕，则关闭合并文件的写入流
        writeStream.end();
        writeStream.on('finish', () => {
          console.log('所有分片合并完成');
          res.status(200).send('文件合并成功');
        });
      } else {
        processChunk(i + 1);
      }
    });

    readStream.on('error', (err) => {
      console.error(`分片 ${i} 读取失败:`, err);
      hasError = true;// 如果有错误发生，则设置错误标志
      res.status(500).send(`分片 ${i} 读取失败`);
      writeStream.destroy(); // 关闭写入流
    });
  }

  processChunk(0);
}


// 文件合并接口
router.post('/merge', (req, res) => {
  const fileName = decodeURIComponent(req.body.fileName); // 对文件名进行解码
  const totalChunks = req.body.totalChunks;// 文件总片数
  const originalChecksum = req.body.originalChecksum; // 原始文件校验和
  const filePath = path.join(uploadDir, fileName);// 文件路径
  const writeStream = fs.createWriteStream(filePath);// 文件路径
  let chunksWritten = 0;
  const num = 0;
  let hasError = false;// 标记是否有错误

  // 准备一个函数来处理流的结束情况
  const checkFinish = () => {
    if (chunksWritten === totalChunks && !hasError) {
      writeStream.end(); // 所有分片写入完成，关闭文件流
    }
  };

  mergeChunks(totalChunks, uploadDir, fileName, res) //调用合并事件
  
  writeStream.on('finish', async () => { // 文件流写入完成 
    console.log(`文件 ${fileName} 合并完成，路径: ${filePath}`);
    res.status(200).send('文件合并完成');
    // 校验文件大小
    try {
      const mergedChecksum = await calculateChecksum(filePath);
      if (mergedChecksum === originalChecksum) {
        console.log('文件校验和匹配，文件合并成功');
        // res.status(200).send('文件合并完成');
      } else {
        console.error('文件校验和不匹配，文件可能已损坏');
        // res.status(500).send('文件校验和不匹配，文件可能已损坏');
      }
    } catch (err) {
      console.error('校验和计算失败:', err);
      //   res.status(500).send('校验和计算失败');
    }
  });


  writeStream.on('error', (err) => {
    console.error('文件合并失败:', err);
    res.status(500).send('文件合并失败');
  });
});



module.exports = router;